package com.alisonyu.spider.Downloader;

import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.web.client.HttpRequest;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class VertxDownloader implements Download {

    private WebClient client;
    private int maxRetryTime = 0;

    public VertxDownloader(){}

    public VertxDownloader(Vertx vertx){
        //加载默认配置
        WebClientOptions options=new WebClientOptions();
        options.setKeepAlive(false);
        options.setUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36");
        //初始化下载器
        this.client=WebClient.create(vertx,options);
    }

    @Override
    public CompletableFuture<HttpResponse> asyncDownload(Request request) {
        CompletableFuture<HttpResponse> future = new CompletableFuture<>();
        HttpRequest<Buffer> rq = getClientRequest(request.getUrl(),request.getMethod());
        rq.send(ar->{
            HttpResponse response = new HttpResponse();
            response.setSuccess(ar.succeeded());
            if (ar.succeeded()){
                String content = ar.result().bodyAsString();
                int code = ar.result().statusCode();
                response.setContent(content);
                response.setStatusCode(code);
                response.setBytes(ar.result().body().getBytes());
            }else{
                //这里是递归调用
                if (request.getRetryTime()<maxRetryTime){
                    request.setRetryTime(request.getRetryTime()+1);
                    CompletableFuture<HttpResponse> _future = asyncDownload(request);
                    _future.thenAccept(future::complete);
                    _future.exceptionally(throwable -> {
                         future.completeExceptionally(throwable);
                         return null;
                    });
                }else{
                    //ar.cause().printStackTrace();
                    future.completeExceptionally(ar.cause());
                }
            }
            future.complete(response);
        });
        return future;
    }

    @Override
    public HttpResponse download(Request request) {
        try {
            return asyncDownload(request).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            HttpResponse response = new HttpResponse();
            response.setSuccess(false);
            return response;
        }

    }

    private HttpRequest<Buffer> getClientRequest(String absUrl, Method method){
        HttpRequest<Buffer> request=client.getAbs(absUrl);
        if(method==Method.GET) return request.method(HttpMethod.GET);
        if(method==Method.POST) return request.method(HttpMethod.POST);
        if(method==Method.PUT) return request.method(HttpMethod.PUT);
        if(method==Method.DELETE) return request.method(HttpMethod.DELETE);
        return request;
    }

    public int getMaxRetryTime() {
        return maxRetryTime;
    }

    public void setMaxRetryTime(int maxRetryTime) {
        this.maxRetryTime = maxRetryTime;
    }
}
